// 文件名：multimap_cluster_members.cpp
// 目的：使用 std::multimap 管理“集群ID -> 节点名”的多重映射，支持查询、迁移与导出排序列表。
// 要点：
//   - equal_range(id) 获取某集群下所有成员；
//   - extract + node handle（C++17）：从容器提取节点以修改键（集群ID）后再插回，实现成员迁移；
//   - 将某一集群成员导出为向量并排序展示。
// 注意：
//   - multimap 的值（成员名）未去重；如需唯一性应改用 multimap<id, set<name>> 或插入前检查；
//   - extract 返回节点句柄，空句柄表示提取失败（未找到或容器为空）。
#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#include <vector>

// 打印指定集群的成员列表（按当前 multimap 的迭代顺序）
void printCluster(const std::multimap<int, std::string>& clusters, int id) {
    auto [begin, end] = clusters.equal_range(id); // 获取 key==id 的区间
    std::vector<std::string> members;
    for (auto it = begin; it != end; ++it) {
        members.push_back(it->second);
    }
    std::cout << "Cluster " << id << ": ";
    if (members.empty()) {
        std::cout << "(empty)\n";
    } else {
        for (const auto& name : members) std::cout << name << ' ';
        std::cout << '\n';
    }
}

int main() {
    // 初始化：多个成员属于同一集群 ID
    std::multimap<int, std::string> clusters = {
        {1, "alpha"}, {1, "beta"}, {1, "gamma"},
        {2, "delta"}, {2, "epsilon"},
        {3, "zeta"}
    };

    printCluster(clusters, 1);
    printCluster(clusters, 2);

    // 使用 node handle 将某个成员从集群 1 迁移到 2（修改键值）
    auto node = clusters.extract(clusters.find(1)); // 提取第一个 key==1 的节点
    if (!node.empty()) {
        node.key() = 2;            // 修改聚类编号（键）
        clusters.insert(std::move(node)); // 重新插入到容器（按新键归位）
    }

    std::cout << "After migrating one member from cluster 1 to 2:\n";
    printCluster(clusters, 1);
    printCluster(clusters, 2);

    // 导出 cluster 2 成员列表为排序向量
    auto [begin, end] = clusters.equal_range(2);
    std::vector<std::string> sortedMembers;
    sortedMembers.reserve(std::distance(begin, end)); // 预留容量以减少扩容
    std::transform(begin, end, std::back_inserter(sortedMembers),
                   [](const auto& kv) { return kv.second; });
    std::sort(sortedMembers.begin(), sortedMembers.end());
    std::cout << "Cluster 2 sorted members:";
    for (const auto& name : sortedMembers) std::cout << ' ' << name;
    std::cout << '\n';

    return 0;
}